package com.klm.client;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.klm.ResultInfo;
//import com.klm.proto.BinaryRequest;
//import com.klm.proto.BinaryResponse;
import com.klm.request.BaseTranslateRequest;
import com.klm.util.SignUtil;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.UUID;

/**
 * @author Administrator
 */
@Slf4j
@Component
public class TranslateClient {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private ObjectMapper objectMapper;

    private final String host;
    private final int port;
    private final String appKey;
    private final String appSecret;
    private final EventLoopGroup group;
    private Channel channel;
    //private final Map<String, CompletableFuture<BinaryResponse>> pendingRequests = new ConcurrentHashMap<>();
    private volatile boolean isConnected = false;

    public TranslateClient(String host, int port, String appKey, String appSecret) {
        this.host = host;
        this.port = port;
        this.appKey = appKey;
        this.appSecret = appSecret;
        this.group = new NioEventLoopGroup();
    }

    /**
     * 执行HTTP请求
     */
    public <T, R> R executeRequest(T request, HttpMethod method, Class<R> responseType) {
        String requestId = UUID.randomUUID().toString();
        long startTime = System.currentTimeMillis();
        
        try {
            if (!(request instanceof BaseTranslateRequest baseRequest)) {
                throw new IllegalArgumentException("Request must extend BaseTranslateRequest");
            }

            String url = baseRequest.getServerUrl();
            log.info("[HTTP Client] [{}] Sending request to: {}", requestId, url);

            // 添加认证头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            addAuthHeaders(headers);

            ResponseEntity<ResultInfo<R>> response;
            if (method == HttpMethod.GET || method == HttpMethod.DELETE) {
                response = restTemplate.exchange(url, method, new HttpEntity<>(headers),
                        new ParameterizedTypeReference<ResultInfo<R>>() {});
            } else {
                HttpEntity<T> entity = new HttpEntity<>(request, headers);
                response = restTemplate.exchange(url, method, entity,
                        new ParameterizedTypeReference<ResultInfo<R>>() {});
            }

            ResultInfo<R> resultInfo = response.getBody();
            if (resultInfo == null) {
                throw new RuntimeException("Response body is null");
            }

            if (!resultInfo.isSuccess()) {
                throw new RuntimeException("Request failed: " + resultInfo.getResultMessage());
            }

            long duration = System.currentTimeMillis() - startTime;
            log.info("[HTTP Client] [{}] Request completed successfully in {}ms", requestId, duration);
            return resultInfo.getBody();
            
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("[HTTP Client] [{}] Request failed after {}ms: {}", requestId, duration, e.getMessage(), e);
            throw new RuntimeException("Request failed: " + e.getMessage(), e);
        }
    }

//    /**
//     * 连接到服务器
//     */
//    public synchronized void connect() throws InterruptedException {
//        if (isConnected) {
//            return;
//        }
//
//        Bootstrap bootstrap = new Bootstrap();
//        bootstrap.group(group)
//                .channel(NioSocketChannel.class)
//                .option(ChannelOption.TCP_NODELAY, true)
//                .option(ChannelOption.SO_KEEPALIVE, true)
//                .handler(new ChannelInitializer<SocketChannel>() {
//                    @Override
//                    protected void initChannel(SocketChannel ch) {
//                        ch.pipeline()
//                                .addLast(new ProtobufVarint32FrameDecoder())
//                                .addLast(new ProtobufDecoder(BinaryResponse.getDefaultInstance()))
//                                .addLast(new ProtobufVarint32LengthFieldPrepender())
//                                .addLast(new ProtobufEncoder())
//                                .addLast(new SimpleChannelInboundHandler<BinaryResponse>() {
//                                    @Override
//                                    protected void channelRead0(ChannelHandlerContext ctx, BinaryResponse msg) {
//                                        String requestId = msg.getRequestId();
//                                        CompletableFuture<BinaryResponse> future = pendingRequests.remove(requestId);
//                                        if (future != null) {
//                                            future.complete(msg);
//                                        } else {
//                                            log.warn("[Binary Client] Received response for unknown request: {}", requestId);
//                                        }
//                                    }
//
//                                    @Override
//                                    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//                                        log.error("[Binary Client] Channel exception: {}", cause.getMessage(), cause);
//                                        ctx.close();
//                                        isConnected = false;
//                                    }
//
//                                    @Override
//                                    public void channelInactive(ChannelHandlerContext ctx) {
//                                        log.info("[Binary Client] Channel inactive");
//                                        isConnected = false;
//                                    }
//                                });
//                    }
//                });
//
//        try {
//            ChannelFuture future = bootstrap.connect(host, port).sync();
//            channel = future.channel();
//            isConnected = true;
//            log.info("[Binary Client] Connected to {}:{}", host, port);
//        } catch (Exception e) {
//            log.error("[Binary Client] Failed to connect to {}:{}", host, port, e);
//            throw e;
//        }
//    }
//
//    /**
//     * 断开连接
//     */
//    public synchronized void disconnect() {
//        if (channel != null) {
//            channel.close();
//            channel = null;
//        }
//        isConnected = false;
//        group.shutdownGracefully();
//        log.info("[Binary Client] Disconnected");
//    }

//    /**
//     * 执行二进制请求
//     */
//    public <T, R> R executeBinaryRequest(T request, Class<R> responseType) throws Exception {
//        String requestId = UUID.randomUUID().toString();
//        long startTime = System.currentTimeMillis();
//
//        try {
//            if (!isConnected) {
//                connect();
//            }
//
//            if (!(request instanceof BaseTranslateRequest baseRequest)) {
//                throw new IllegalArgumentException("Request must extend BaseTranslateRequest");
//            }
//
//            log.info("[Binary Client] [{}] Sending request to path: {}", requestId, baseRequest.getServerUrl());
//
//            // 生成时间戳和签名
//            long timestamp = System.currentTimeMillis();
//            String signature = SignUtil.generateSignature(appSecret, timestamp);
//
//            // 构建二进制请求
//            BinaryRequest binaryRequest = BinaryRequest.newBuilder()
//                    .setRequestId(requestId)
//                    .setPath(baseRequest.getServerUrl())
//                    .setRequestData(ByteString.copyFrom(objectMapper.writeValueAsBytes(request)))
//                    .setAppKey(appKey)
//                    .setTimestamp(timestamp)
//                    .setSignature(signature)
//                    .build();
//
//            // 发送请求并等待响应
//            BinaryResponse response = sendRequest(binaryRequest);
//
//            // 检查响应状态
//            if (response.getCode() != 200) {
//                long duration = System.currentTimeMillis() - startTime;
//                log.error("[Binary Client] [{}] Request failed after {}ms with code {}: {}",
//                    requestId, duration, response.getCode(), response.getMessage());
//                throw new RuntimeException("Request failed: " + response.getMessage());
//            }
//
//            // 解析响应数据
//            ResultInfo<R> resultInfo = objectMapper.readValue(response.getData().toByteArray(),
//                objectMapper.getTypeFactory().constructParametricType(ResultInfo.class, responseType));
//
//            if (!resultInfo.isSuccess()) {
//                long duration = System.currentTimeMillis() - startTime;
//                log.error("[Binary Client] [{}] Business logic failed after {}ms: {}",
//                    requestId, duration, resultInfo.getResultMessage());
//                throw new RuntimeException("Request failed: " + resultInfo.getResultMessage());
//            }
//
//            long duration = System.currentTimeMillis() - startTime;
//            log.info("[Binary Client] [{}] Request completed successfully in {}ms", requestId, duration);
//
//            return resultInfo.getBody();
//
//        } catch (Exception e) {
//            long duration = System.currentTimeMillis() - startTime;
//            log.error("[Binary Client] [{}] Request failed after {}ms: {}", requestId, duration, e.getMessage(), e);
//            throw e;
//        }
//    }
//
//    private BinaryResponse sendRequest(BinaryRequest request) throws Exception {
//        CompletableFuture<BinaryResponse> future = new CompletableFuture<>();
//        pendingRequests.put(request.getRequestId(), future);
//
//        log.debug("[Binary Client] [{}] Preparing to send request", request.getRequestId());
//
//        ByteBuf buf = Unpooled.buffer();
//        byte[] requestBytes = request.toByteArray();
//        buf.writeBytes(requestBytes);
//
//        channel.writeAndFlush(buf).addListener((ChannelFutureListener) f -> {
//            if (!f.isSuccess()) {
//                log.error("[Binary Client] [{}] Failed to send request: {}",
//                    request.getRequestId(), f.cause().getMessage());
//                future.completeExceptionally(f.cause());
//            } else {
//                log.debug("[Binary Client] [{}] Request sent successfully", request.getRequestId());
//            }
//        });
//
//        try {
//            return future.get(5, TimeUnit.SECONDS);
//        } catch (Exception e) {
//            pendingRequests.remove(request.getRequestId());
//            log.error("[Binary Client] [{}] Request timed out or failed: {}",
//                request.getRequestId(), e.getMessage());
//            throw e;
//        }
//    }

    /**
     * 添加认证头
     */
    private void addAuthHeaders(HttpHeaders headers) {
        long timestamp = System.currentTimeMillis();
        String signature = SignUtil.generateSignature(appSecret, timestamp);
        
        headers.set("X-App-Key", appKey);
        headers.set("X-Timestamp", String.valueOf(timestamp));
        headers.set("X-Signature", signature);
    }
}
